package com.wh.wisdomsite.xbox.server.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wh.wisdomsite.xbox.common.ServiceMethodHandler;
import com.wh.wisdomsite.xbox.common.XboxRequestContext;
import com.wh.wisdomsite.xbox.core.interceptor.AbstractInterceptor;
import com.wh.wisdomsite.xbox.core.session.impl.SimpleSession;
import com.wh.wisdomsite.xbox.common.annotation.Token;
import com.wh.wisdomsite.xbox.utils.Const;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.UUID;


/***
 * 方法拦截
 * @Package com.wh.wisdomsite.xbox.server.interceptor
 * @author 谢泽鹏
 * @date 2016年11月07日 下午15:10
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2016
 * @version V1.0
 */
public class MethodTokenInteceptor extends AbstractInterceptor {

    private static final Log logger = LogFactory.getLog(MethodTokenInteceptor.class);

    public final static String TOKEN_KEY = "token_key";


    /**
     * 方法前拦截(调用服务之前)
     * @param xboxRequestContext
     */
    @Override
    public void beforeService(XboxRequestContext xboxRequestContext) {
        logger.debug("***************开始执行: " + xboxRequestContext.getMethod() + "***************");
        handleBefore(xboxRequestContext);
    }

    /**
     * 响应前拦截(调用服务之后)
     * @param xboxRequestContext
     */
    @Override
    public void beforeResponse(XboxRequestContext xboxRequestContext) {
        logger.debug("***************结束执行: " + xboxRequestContext.getMethod() + "***************");
        handleAfter(xboxRequestContext);
    }


    /**
     * 该方法返回true时才实施拦截，否则不拦截
     * @param xboxRequestContext
     * @return
     */
    @Override
    public boolean isMatch(XboxRequestContext xboxRequestContext) {
        return true;
    }

    /**
     * 执行的顺序，整数值越小的越早执行(放在拦截器链的最后)
     * @return
     */
    public int getOrder() {
        return Integer.MAX_VALUE;
    }


    /**
     * 方法前调用
     * @param xboxRequestContext
     */
    private void handleBefore(XboxRequestContext xboxRequestContext){
        ServiceMethodHandler methodHandler = xboxRequestContext.getServiceMethodHandler();
        Method method = methodHandler.getMethod();
        Token annotation = method.getAnnotation(Token.class);
        if(null != annotation){
            boolean reomveToken = annotation.remove();
            if(reomveToken){
                if(!validToken(xboxRequestContext)){
                    JSONObject json = new JSONObject();
                    json.put("code", Const.REQUEST_REPEAT_COMMIT);
                    json.put("message", "请求重复提交");
                    xboxRequestContext.setXboxResponse(json);
                }
            }

        }
    }

    /**
     * 方法后调用
     * @param xboxRequestContext
     */
    private void handleAfter(XboxRequestContext xboxRequestContext){
        ServiceMethodHandler methodHandler = xboxRequestContext.getServiceMethodHandler();
        Method method = methodHandler.getMethod();
        Token annotation = method.getAnnotation(Token.class);
        if(null != annotation){
            boolean saveToken = annotation.save();
            if (saveToken) {
                addToken(xboxRequestContext);
            }
        }
    }

    /**
     * 添加token
     * @param xboxRequestContext
     */
    private void addToken(XboxRequestContext xboxRequestContext){
        String token = UUID.randomUUID().toString();
        SimpleSession session = new SimpleSession();
        session.setAttribute("method", xboxRequestContext.getMethod());
        xboxRequestContext.addSession(token, session);
        //返回token值
        Object response = xboxRequestContext.getXboxResponse();
        JSONObject json = JSON.parseObject(JSON.toJSONString(response));
        json.put("token",token);
        xboxRequestContext.setXboxResponse(json);
    }

    /**
     * 验证token
     * @param xboxRequestContext
     * @return
     */
    private boolean validToken(XboxRequestContext xboxRequestContext){
        //获取token值
        Map<String, String> params = xboxRequestContext.getAllParams();
        String token = params.get("token");
        if(StringUtils.isEmpty(token))
            return false;
        SimpleSession session = (SimpleSession)xboxRequestContext.getXboxContext().getSessionManager().getSession(token);
        if(null == session)
            return false;
        xboxRequestContext.getXboxContext().getSessionManager().removeSession(token);
        return true;
    }
}
